import os
from time import time

import bpy
from bpy.props import BoolProperty, StringProperty, CollectionProperty
from bpy.types import Operator
from bpy.types import PropertyGroup

from ..utils.log import log
from ..utils import QueueUtils
from ..utils.render_item import RenderItem


class SwitchQueueUI(Operator, QueueUtils):
    bl_idname = 'wm.render_queue_switch_ui'
    bl_label = '切换渲染队列UI'

    popup_window: BoolProperty(default=False, name='弹出窗口',
                               options={'SKIP_SAVE', })

    def execute(self, context):
        if self.popup_window:
            bpy.ops.screen.userpref_show()

        from ..ui import PreferencesUI
        PreferencesUI.switch()
        self.show_header(context)
        context.preferences.active_section = 'ADDONS'
        bpy.ops.wm.redraw_timer(type='DRAW_WIN')
        return {'FINISHED'}

    @staticmethod
    def show_header(context: bpy.context):
        def set_header(areas: list[bpy.types.Area]):
            for area in areas:
                if area.type == 'PREFERENCES':
                    area.spaces[0].show_region_header = True

        for win in context.window_manager.windows:
            set_header(win.screen.areas)


class FilesCol(PropertyGroup):
    """选择文件用属性
    INFO 如果没有这个属性将会闪退
    """


class RenderStateSet(bpy.types.Operator, QueueUtils):
    bl_idname = 'render.render_queue_set_state'
    bl_label = '设置渲染状态'
    bl_description = '''设置所有选中项的渲染的状态
    如果项路径有效
    '''

    state: StringProperty(name='状态')

    def execute(self, context):
        for item in self.pref.render_items:
            if item.selected and item.valid:
                item.render_state = self.state
        return {'FINISHED'}


class RenderSwitchFinished(bpy.types.Operator, QueueUtils):
    bl_idname = 'render.render_queue_switch_finished'
    bl_label = '切换渲完成项状态'
    bl_description = '''设置所有渲染完成项的渲染的状态'''

    def execute(self, context):
        for item in self.pref.render_items:
            if item.is_rendered and item.valid:
                item.switch_state()
        return {'FINISHED'}


class RenderClearInvalidItem(bpy.types.Operator, QueueUtils):
    bl_idname = 'render.render_queue_clear_invalid_item'
    bl_label = '清理无效项'

    def execute(self, context):
        while True:
            valid_items = [item for item in self.pref.render_items if not item.valid]

            if not valid_items:
                break
            for item in valid_items:
                item.remove()
        return {'FINISHED'}


class RenderStateSwitch(bpy.types.Operator, QueueUtils):
    bl_idname = 'render.render_queue_switch_state'
    bl_label = '切换渲染状态'
    bl_description = '''切换渲染的状态
    Shift 点击:将已渲染项切换为待渲染
    '''

    def invoke(self, context, event: 'bpy.types.Event'):
        item = context.render_queue

        if event.shift and (not item.is_rendered):
            '''如果不是渲染完成的就不管这个
            是渲染完成的还给弄成不渲染的
            '''
            return {'FINISHED'}
        return self.execute(context)

    def execute(self, context):
        item = context.render_queue
        item.switch_state()
        return {'FINISHED'}


class RenderQueueAdd(bpy.types.Operator, QueueUtils):
    bl_idname = 'render.render_queue_add_element'
    bl_label = '添加渲染文件'
    bl_description = '''
    单击: 添加项(无路径)
    
    ctrl or shift: 从文件或文件夹添加项
    
    只添加项,自已设置目录
    '''

    render_file_path: StringProperty(subtype='FILE_PATH',
                                     options={'HIDDEN'},
                                     )

    render_folder_path: StringProperty(subtype='DIR_PATH',
                                       options={'HIDDEN'},
                                       )
    find_child_folder: BoolProperty(name='查找子级文件夹')

    # selected file
    filename_ext = ".blend"

    filter_glob: StringProperty(
        default="*.blend",
        options={'HIDDEN'},
        maxlen=255,  # Max internal buffer length, longer would be clamped.
    )

    filepath: StringProperty(
        name="File Path",
        description="Filepath used for importing the file",
        maxlen=1024,
        subtype='FILE_PATH',
    )
    directory: StringProperty(
    )

    filename: StringProperty(
    )
    files: CollectionProperty(type=FilesCol, )
    start_time: str

    def invoke(self, context: 'bpy.types.Context', event: 'bpy.types.Event') -> set:
        if event.shift or event.ctrl:
            context.window_manager.fileselect_add(self)
            return {'RUNNING_MODAL'}
        else:
            queue = self.add_queue()
            queue.name = 'the is a queue'
            return {'FINISHED'}

    def execute(self, context):
        self.set_queue(context)
        return {'FINISHED'}

    def set_queue(self, context):
        """
        多选文件
        单选文件
        文件夹
        """

        log.debug(self, context)
        log.debug(self.render_file_path)
        log.debug(self.filepath, )
        log.debug(self.directory, )
        log.debug(self.files, )

        self.__class__.start_time = time()
        if len(self.files) > 1:
            self.from_files_add_queue()
        elif self.filepath and self.is_bl_file(self.filepath):
            self.from_file_add_queue(self.filepath)
        elif self.directory:
            self.from_folder_add_queue(self.filepath, self.find_child_folder)
        else:
            log.info('啥也没有啊这是 没有选中')

    @classmethod
    def from_folder_add_queue(cls, folder_path: str, find_child: 'bool'):
        """从文件夹添加队列

        Args:
            folder_path (str): 文件夹路径
            find_child (bool): 是否查找子级的布尔值
        """
        _walk = list(os.walk(folder_path))
        walk = _walk if find_child else _walk[:1]
        for path, folders, files in walk:
            if (time() - cls.start_time) > 10:
                # 如果导入时间大于10s说明选择的目录子目录太深,取消导入
                log.error(f"文件目录过深 请重新选择一个子目录较少的文件夹 :{folder_path}")
                return

            for file in files:
                if cls.is_bl_file(file):
                    file_path = os.path.join(path, file)
                    cls.from_file_add_queue(file_path)

    def from_files_add_queue(self) -> None:
        """从多个文件添加队列"""
        for file in self.files:
            blend_file = os.path.join(self.directory, file.name)
            self.from_file_add_queue(blend_file)

    @classmethod
    def from_file_add_queue(cls, file_path: 'str'):
        """从文件添加队列"""
        queue = cls.add_queue()
        queue.render_blend_file = file_path
        log.info(f'add queue\t{file_path}')

    @classmethod
    def add_queue(cls) -> 'RenderItem':
        """添加一个队列项"""
        pref = QueueUtils.pref_()
        return pref.render_items.add()

    def draw(self, context):
        layout = self.layout
        col = layout.column()
        col.prop(self, 'find_child_folder')


class RenderQueueRemove(bpy.types.Operator, QueueUtils):
    bl_idname = 'render.render_queue_remove'
    bl_label = '删除一个渲染队列项'

    queue_name: StringProperty()

    def execute(self, context):
        items = self.pref.render_items
        item = items.get(self.queue_name)
        if item:
            item.remove()
        return {'FINISHED'}


class RenderQueueStart(bpy.types.Operator, QueueUtils):
    bl_idname = 'render.render_queue_start_render'
    bl_label = '开始渲染'

    @classmethod
    def poll(cls, context):
        return len(cls.pref_().render_items)

    def execute(self, context):
        for item in self.render_not_items:  # 将未渲染的放在渲染队列里面
            item.render_state = 'IN_QUEUE'
        log.info(f"开始渲染 {self.bl_idname, self.render_not_items}")

        return {'FINISHED'}


class RenderQueueStop(bpy.types.Operator, QueueUtils):
    bl_idname = 'render.render_queue_stop_render'
    bl_label = '停止渲染'

    @classmethod
    def poll(cls, context):
        return cls.render_queue

    def execute(self, context):
        self.pref.stop_all_render()
        return {'FINISHED'}


class RenderFromFileNew(bpy.types.Operator, QueueUtils):
    bl_idname = 'render.render_queue_from_file_new'
    bl_label = '从文件或文件夹新建队列'
    '''TODO new'''


class RenderQueueRefresh(bpy.types.Operator, QueueUtils):
    bl_idname = 'render.render_queue_clear_cache'
    bl_label = '刷新队列'

    def execute(self, context):
        self.pref.clear_cache()
        return {'FINISHED'}


def clear_queue(self, context):
    self.pref.render_items.clear()
    return {'FINISHED'}


RenderQueueClear = type('RenderClear', (bpy.types.Operator, QueueUtils), {
    'execute': clear_queue,
    'bl_idname': 'render.render_queue_clear',
    'bl_label': '清除渲染队列',
    'bl_description': '清除所有的渲染项,将里面的所有项都清掉',
})

class_tuple = (
    SwitchQueueUI,

    FilesCol,

    RenderQueueAdd,
    RenderQueueRemove,

    RenderStateSet,
    RenderSwitchFinished,
    RenderClearInvalidItem,

    RenderQueueClear,
    RenderQueueStart,
    RenderQueueStop,
    RenderStateSwitch,

    RenderQueueRefresh,
)

reg_class, un_reg_class = bpy.utils.register_classes_factory(class_tuple)


def register():
    reg_class()


def unregister():
    un_reg_class()
